package com.calvin.study.threadsafe.sync;

import com.calvin.study.utils.Print;

public class SyncDemo01 {
	
	public static void main(String[] args) {
		TwoPlus p = new TwoPlus();
		
		for (int i = 1, len = 10; i <= len; i++) {
			new Thread(() -> {
				p.plus(5,0);
			}, String.valueOf(i)).start();
		}
		
//		for (int i = 1, len = 10; i <= len; i++) {
//			new Thread(() -> {
//				p.plus(0, 1);
//			}, String.valueOf(i)).start();
//		}
		
		Print.tcfo(p.getSum1());
		Print.tcfo(p.getSum2());
	}

}

class TwoPlus {
	
	private int sum1 = 0;
	private int sum2 = 0;

	//临界区代码段包含了对两个临界区资源的操作， 这两个临界区资源分别为sum1、sum2。 
	//使用synchronized对plus(int val1, int val2)进行同步保护之后， 进入临界区代码段的线程拥有sum1、 sum2的操作权， 并且是全部占用。
	//一旦线程进入， 当线程在操作sum1而没有操作sum2时，也将sum2的操作权白白占用， 其他的线程由于没有进入临界区， 只能看着sum2被闲置而不能去执行操作。
	//所以， 将synchronized加在方法上， 如果其保护的临界区代码段包含的临界区资源（要求是相互独立的） 多于一个， 会造成临界区资源的闲置等待， 这就会影响临界区代码段的吞吐量。 
	//为了提升吞吐量， 可以将synchronized关键字放在函数体内， 同步一个代码块。
//	public synchronized void plus(int val1, int val2) {
//		this.sum1 += val1;
//		this.sum2 += val2;
//	}
	
	private Integer sum1Lock = new Integer(1); // 同步锁一
	private Integer sum2Lock = new Integer(2); // 同步锁二


	
	public int getSum1() {
		return sum1;
	}
	
	public int getSum2() {
		return sum2;
	}
	
	
	public void plus(int val1,int val2) {
		synchronized (this.sum1Lock) {
			this.sum1 += val1;
		}
		
		synchronized (this.sum2Lock) {
			this.sum2 +=val2;
		}
	}
}
